package com.cskaoyan.javse.oop3._1interface._0introduction;

/**
 * @description: 接口的引入
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

import org.omg.CORBA.PUBLIC_MEMBER;

/**
 * > 引例
 * > 回想Animal继承体系的案例，现在我们把Animal设计成抽象类
 * > 产品经理给了新需求
 * - 现在有一部分猫和狗，经过了特殊训练
 *   - 都可以直立行走（Walk Upright）和骑自行车（Ride Bike）
 * - 那么该怎么去描述这群具有特殊行为的猫狗呢？
 *
 * 直立行走(walkUpright)和骑自行车(rideBike)对应类中两个方法,这两个方法应该放在哪里?
 * 可以考虑重新定义SuperCat,SuperDog类,然后让它们新增两个方法,这样做是可以实现需求的,但是也有一些问题:
 *      1.代码有重复,可以考虑复用它们
 *      2.实际上在这个案例中,只有通过了特殊训练的猫和狗才能够有特殊的行为,直接定义方法的形式没有办法体现训练的过程
 *          假如🐖也想骑自行车,大象也想直立行走
 * 以上,我们可以考虑提取出这两个方法,然后放在一个类中,甚至可以把它们作为抽象方法,放进抽象类中,任何继承抽象类的类都可以实现
 *      骑自行车和直立行走,这就是体现了训练的过程
 *
 * 但是想法是好的,现实却是做不到的,因为java不支持多继承,一个类无法直接继承两个类,所以在这里class继承的定义就限制了我们,我们需要一种全新的数据类型,这种数据类型要求不受多继承限制,可以完成我们的需求,这就是接口.
 *
 * 接口是和class类同等级别的数据类型,同属于引用数据类型,它的使用和class类有很多相似的地方
 * 接口的定义/语法:
 * [访问权限修饰符] interface 接口名{
 *     //接口体
 * }
 * 解释:
 *      1.接口的访问权限修饰符也只有两种: public 和 缺省(含义也是一样的)
 *      2.接口名和类名一样,遵循大驼峰式的书写规范,并且在很多时候,程序员喜欢在一个接口的实际名字前面加上一个大写字母"I",用于表示它是一个接口
 *      3.接口中可以定义抽象方法,接口也是抽象的
 *          接口也不能创建对象(这点和抽象类相似)
 *      4.接口的"继承",接口是可以被一个普通类"继承"的,称之为接口的实现,它也不再使用extends关键字,而是使用implements关键字,在接口的实现中,可以称呼接口为"父接口",接口的实现类为"子类",它们仍然是父子关系
 *      5.普通类实现接口,必须实现接口中的所有抽象方法
 *      6.接口不受多继承限制,一个类可以在继承别的类的同时实现接口,甚至可以实现多个接口
 *      7.如果一个类实现接口并继承别的类,要"先继承再实现"
 *      8.类实现接口也可以认为接口是"父类",实现类是"子类".在使用上这么认为完全没问题
 *          仍然可以用父类引用指向子类对象
 *
 * 为什么这个案例中使用接口比抽象类更好,接口的好处是什么?
 *      1.接口不受多继承限制,这是接口非常重要的优点
 *      2.抽象类终究是一个类,它和子类的关系,仍然是"is-a"关系.但是有些场景中,父子类可能没有"is-a"关系,纯粹为了复用成员,扩展一些功能,这时候再使用抽象类也不符合设计原则了
 *      而接口不是类,它和它的实现类,也不需要存在"is-a"关系,接口比抽象类使用更加灵活
 *      3.我们把接口和它的实现类之间的关系称之为"like-a",像xxx的关系
 *      4.接口的本质不是继承那样去考虑"is-a"关系,接口更多的是表示对功能的扩展,接口表示一种标准和规范,只要实现接口,就能够完成某种功能
 *
 */
public class Demo {
    public static void main(String[] args) {
        //'ISpecialSkill' is abstract; cannot be instantiated
        //ISpecialSkill iSpecialSkill = new ISpecialSkill();

        ISpecialSkill ips = new SuperCat();
        ips.rideBike();
        ips.walkUpright();
        SuperCat sc = (SuperCat) ips;
        sc.shout();
        ISpecialSkill ips2 = new SuperDog();

        IA ia = new SuperCat();
        Cat c = new SuperCat();
        c.shout();

    }
}
abstract class Animal {
    public abstract void shout();
}
class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}
class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}
class SuperCat extends Cat implements ISpecialSkill,IA{
    @Override
    public void walkUpright(){
        System.out.println("直立行走");
    }
    @Override
    public void rideBike(){
        System.out.println("骑自行车");
    }
}
class SuperDog extends Dog implements ISpecialSkill,IA{
    @Override
    public void walkUpright(){
        System.out.println("直立行走");
    }
    @Override
    public void rideBike(){
        System.out.println("骑自行车");
    }
}
abstract class AbstractSpecialSkill{
    public abstract void walkUpright();
    public abstract void rideBike();
}
interface ISpecialSkill{
    public abstract void walkUpright();
    public abstract void rideBike();
}
interface IA{}